package com.douqu.game.battle.server.netty;


import com.douqu.game.battle.controller.BattleController;
import com.douqu.game.battle.controller.sprite.PlayerController;
import com.douqu.game.battle.entity.aobject.BattleAObject;
import com.douqu.game.battle.entity.tmp.PlayerBattleTmp;
import com.douqu.game.battle.server.BattleInitInfo;
import com.douqu.game.battle.server.BattleInitTarget;
import com.douqu.game.battle.server.GameServer;
import com.douqu.game.battle.server.WorldManager;
import com.douqu.game.battle.util.MsgUtils;
import com.douqu.game.core.config.StableDataConfig;
import com.douqu.game.core.e.E_BattleDetailType;
import com.douqu.game.core.e.E_BattleEnd;
import com.douqu.game.core.e.E_PlayerStatus;
import com.douqu.game.core.e.E_StableDataType;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.entity.db.CardDB;
import com.douqu.game.core.factory.*;
import com.douqu.game.core.netty.NettyConnection;
import com.douqu.game.core.protobuf.SGMainProto;
import com.douqu.game.core.protobuf.SGSystemProto;
import com.douqu.game.core.protobuf.SGWarProto;
import com.douqu.game.core.util.CoreUtils;
import com.douqu.game.core.util.LogUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

import java.io.IOException;
import java.rmi.RemoteException;


/**
 * 服务器继承ChannelInboundHandlerAdapter这个类,收的ByteBuf需要手动释放
 * Created by bean on 2017/3/9.
 */
public class NettyTCPServerHandler extends ChannelInboundHandlerAdapter {

    private NettyConnection connection;

//    private PlayerController playerController;

    private void close()
    {
        Object object = connection.getObject();
        if(object != null && object instanceof PlayerController)
        {
            PlayerController playerController = (PlayerController) object;
            if(playerController != null)
            {
                if(CodeFactory.TEST)
                {
                    if(playerController.getBattleController() != null)
                    {
                        if(playerController.getAttachment() != null)
                        {
                            int winTeam = playerController.getAttachment().getTeamNo() == ConstantFactory.BATTLE_TEAM_1 ? ConstantFactory.BATTLE_TEAM_2 : ConstantFactory.BATTLE_TEAM_1;
                            LogUtils.warn("玩家离线，自动算输 -> " + playerController.getName() + " battle:" + playerController.getBattleController() + " host:" + connection.getChannel().remoteAddress());
                            playerController.getBattleController().end(winTeam, E_BattleEnd.OFFLINE);
                        }
                        else
                        {
                            LogUtils.error("battleController not null,but attachment is null -> " + playerController.getName() + " battle:" + playerController.getBattleController());
                            GameServer.getInstance().getWorldManager().playerExitGame(playerController);
                        }
                    }
                    else
                    {
                        LogUtils.error("battleController is null -> " + playerController.getName() + " " + connection.getChannel().remoteAddress());
                        GameServer.getInstance().getWorldManager().playerExitGame(playerController);
                    }
                }
                else
                {
                    try {
                        if(playerController.getStatus() != E_PlayerStatus.FREE)
                        {
                            GameServer.getInstance().getIMainServer().updateStatus(playerController.getObjectIndex(), E_PlayerStatus.BATTLE_OFFLINE.name());
                        }
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }

                    playerController.destroy();
                }
            }
        }

        connection.destroy();

//        GameServer.getInstance().getWorldManager().removeConnection(connection);
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception
    {
        if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE)
            {
                LogUtils.info("Reader Timeout!" + connection);
                close();
            }
        }
    }

//    @Override
//    public void handlerRemoved(ChannelHandlerContext ctx)
//    {
//        LogUtils.debug("Client handlerRemoved Disconnect:"+playerController);
//
//        close();
//    }


    /*
      * channelAction
      *
      * 当客户端主动链接服务端的链接后，这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
      *
      */
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

        LogUtils.warn("Client Connect Success -> " + ctx.channel().remoteAddress());

        connection = new NettyConnection(ctx.channel(), DataFactory.currentTime);

//        GameServer.getInstance().getWorldManager().addConnection(connection);


    }



    /*
     * channelInactive
     *
     *
     * 当客户端主动断开服务端的 链接后，这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     *
     */
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

        LogUtils.warn("Client Disconnect -> " + connection.getChannel().remoteAddress());

        close();

        ctx.close();
    }


//    @Override
//    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
//    {
//        LogUtils.info("channelRead---------------------");
//        channelRead0(ctx, msg);
//    }

    /**
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
    {
        ByteBuf byteBuf = (ByteBuf) msg;

//        int code = BufferUtils.readShort(byteBuf);
        int code = byteBuf.readShortLE();

        LogUtils.info("收到指令->" + SGMainProto.E_MSG_ID.forNumber(code) + "->" + code + "  connection:" + (connection == null ? "null" : connection.getRemoteAddress()));

        try{

            if(SGMainProto.E_MSG_ID.MsgID_System_BattleReconnect_VALUE == code)
            {
                if(connection.getObject() != null)
                {
                    connection.sendUnknown();
                    return;
                }

                byte[] data = CoreUtils.byteBufToBytes(byteBuf);
                SGSystemProto.C2S_BattleReconnect request = SGSystemProto.C2S_BattleReconnect.parseFrom(data);
                String battleId = request.getBattleId();
                String playerIndex = request.getPlayerIndex();
                WorldManager worldManager = GameServer.getInstance().getWorldManager();
                BattleController battleController = worldManager.getBattleController(battleId);
                if(battleController == null)
                {
                    //TODO 战斗已经结束或者战斗不存在，提示客户端去连接主服务器
                    connection.sendUnknown();
                    return;
                }

                PlayerController playerController = worldManager.getPlayerController(playerIndex);
                if(playerController == null || battleController.getPlayerByIndex(playerIndex) == null)
                {
                    //玩家数据不存在，参数错误
                    connection.sendUnknown();
                    return;
                }

                try {
                    GameServer.getInstance().getIMainServer().updateStatus(playerController.getObjectIndex(), playerController.getStatus().name());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

                playerController.setTcpConnection(connection);
                connection.setObject(playerController);

                //返回数据
                SGSystemProto.S2C_BattleReconnect.Builder response = SGSystemProto.S2C_BattleReconnect.newBuilder();
                response.setBattleId(battleId);
                response.setPlayerIndex(playerIndex);
                response.setBattleType(battleController.getBattleType());

                PlayerBattleTmp playerBattleTmp = (PlayerBattleTmp) playerController.getAttachment();

                response.setTeamNo(playerBattleTmp.getTeamNo());
                response.setSelfMaster(playerBattleTmp.getMasterSoldier().parseBattleUnit());
                response.setOtherMaster(playerBattleTmp.getTargetBattleTmp().getMasterSoldier().parseBattleUnit());
                for(CardDB cardDB : playerBattleTmp.getCardList())
                {
                    response.addCardId(cardDB.id);
                }

                for(BattleAObject battleAObject : battleController.getSoldiers())
                {
                    response.addSoldier(battleAObject.parseBattleUnit());
                }

                playerController.sendMsg(SGMainProto.E_MSG_ID.MsgID_System_BattleReconnect_VALUE, response.build().toByteArray());
            }
            else if(SGMainProto.E_MSG_ID.MsgID_War_Create_VALUE == code)
            {
                if(connection.getObject() != null)
                {
                    LogUtils.error("重复请求Create----------" + connection.getChannel().remoteAddress() + " -> " + connection.getObject());
                    connection.sendUnknown();
                    return;
                }

                //创建战斗
                byte[] data = CoreUtils.byteBufToBytes(byteBuf);
                SGWarProto.C2S_Create request = SGWarProto.C2S_Create.parseFrom(data);
//                String battleId = request.getBattleId();
                WorldManager worldManager = GameServer.getInstance().getWorldManager();
                BattleInitInfo battleInitInfo = worldManager.getBattleInitInfo(request.getBattleId());
                if(battleInitInfo == null)
                {
                    //非法请求
                    LogUtils.error("战斗不存在或已经超时:" + request.getBattleId() + " -> " + connection.getChannel().remoteAddress() + " -> " + connection.getObject());
                    connection.sendUnknown();
//                    connection.sendWarn(WordFactory.BATTLE_CONNECT_TIMEOUT);
                    return;
                }
                String battleId = battleInitInfo.getBattleId();
                //玩家流水号
                String playerIndex = request.getPlayerIndex();
                BattleInitTarget battleInitPlayer = battleInitInfo.getBattleInitTarget(playerIndex);
                if(battleInitPlayer == null)
                {
                    //数据异常
                    LogUtils.error("数据异常:battleId -> " + battleId + " playerIndex -> " + playerIndex + " -> " + connection.getChannel().remoteAddress() + " -> " + connection.getObject());
                    connection.sendUnknown();
//                    connection.sendWarn(WordFactory.BATTLE_CONNECT_TIMEOUT);
                    return;
                }

                Player player = GameServer.getInstance().getIMainServer().getOnlinePlayer(playerIndex);
                if(player == null)
                {
                    //玩家不在线了
                    LogUtils.error("玩家不在线:battleId -> " + battleId + " playerIndex -> " +  playerIndex + " -> " + connection.getChannel().remoteAddress() + " -> " + connection.getObject());
                    connection.sendUnknown();
//                    connection.sendWarn(WordFactory.BATTLE_CONNECT_TIMEOUT);
                    return;
                }

                LogUtils.warn("收到创建战斗的指令:" + playerIndex + "  battleInitInfo: " + battleInitInfo + " connection -> " + connection.getChannel().remoteAddress());

                PlayerController playerController = new PlayerController(player, connection, battleInitPlayer.getServerId());
                boolean autoBattle = false;
                if(E_BattleDetailType.PVP_AI_ARENA == battleInitInfo.getBattleDetailType())
                    autoBattle = true;
                else
                {
                    if(request.getAutoBattle())
                    {
                        autoBattle = true;

                        StableDataConfig stableData = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY, E_StableDataType.AUTO_BATTLE_VIP_LV.getCode());
                        if(stableData != null && playerController.getPlayer().getVipLevel() < stableData.intValue)
                        {
                            String errorMessage = CoreUtils.checkFunctionOpen(FunctionFactory.UNLOCK_AUTO_BATTLE,playerController.getPlayer());
                            if (errorMessage != null){
                                LogUtils.error(errorMessage);
                                autoBattle = false;
                            }
                        }
                    }
                }
                playerController.setAutoBattle(autoBattle);
                battleInitInfo.initPlayerData(playerController);
                worldManager.playerEnterGame(playerController);

                battleInitInfo.ready(playerIndex);

                if(battleInitInfo.isReady())
                {
                    MsgUtils.createPlayerBattle(battleInitInfo);
                }
            }
            else
            {
                Object object = connection.getObject();
                if(object == null)
                {
                    LogUtils.error("1非法请求 -> " + (connection == null ? "null" : connection.getRemoteAddress()) + " code -> " + SGMainProto.E_MSG_ID.forNumber(code));
                    connection.sendUnknown();
                    return;
                }

                if(!(object instanceof PlayerController))
                {
                    LogUtils.error("2非法请求 -> " + (connection == null ? "null" : connection.getRemoteAddress()) + " code -> " + SGMainProto.E_MSG_ID.forNumber(code));
                    connection.sendUnknown();
                    return;
                }

                PlayerController playerController = (PlayerController) object;

                if(playerController.getPlayer().isDel)
                {
                    //被封号了
                    playerController.sendWarn(WordFactory.LOCK_ACCOUNT);
                    return;
                }

//                LogUtils.info("玩家请求战斗信息:" + playerController.getName() + "  " + playerController.getParent());

                if(playerController.getBattleController() != null)
                {
                    playerController.getBattleController().messageChannel(code, playerController, CoreUtils.byteBufToBytes(byteBuf));
                }
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            byteBuf.release();
        }

    }





    /*
     * channelReadComplete
     *
     * channel  通道
     * Read     读取
     * Complete 完成
     *
     * 在通道读取完成后会在这个方法里通知，对应可以做刷新操作
     * ctx.flush()
     *
     */
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    /*
     * exceptionCaught
     *
     * exception	异常
     * Caught		抓住
     *
     * 抓住异常，当发生异常的时候，可以做一些相应的处理，比如打印日志、关闭链接
     *
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
    {
        try{
            if(cause.getClass() != IOException.class)
            {
                cause.printStackTrace();
                close();
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }


}
